<?php
/**
 * 常用工具函数封装
 */

use Illuminate\Http\JsonResponse;
use Illuminate\Support\Arr;


/**
 * 去除空白符
 *
 * @param array|string $val
 * @param int $type 1.去除全部空格；2.去除两头空格
 * @param array|string[] $replace array(" ","　","\t","\n","\r") 去除空格和换行
 *
 * @return array|string|string[]
 */
function removeBlank($val, int $type = 2, array $replace = [" "])
{
    if (is_array($val)) {
        $val_arr = [];
        foreach ($val as $key => $s) {
            $val_arr[$key] = removeBlank($s, $type, $replace);
        }

        return $val_arr;
    } else {
        $val = mergeBlank($val);
        if (1 == $type) {
            $val = str_replace($replace, "", $val);
        } elseif (2 == $type) {
            $val = trim($val);
        }

        return $val;
    }
}

/**
 * 统一空白符为英文空格
 *
 * @param string $val 字符串或数组
 *
 * @return  String
 */
function mergeBlank(string $val): string
{
    //新行 "\x0B" - ASCII;
    return str_replace([" ", " ", "　", "\t", "\n", "\r", "\r\n", "\0", "\x0B", "    ", "   ", "  "],
        " ", $val);
}

/**
 * 输出JSON错误
 *
 * @param int $code
 * @param string $message
 * @param int $statusCode
 *
 * @return JsonResponse
 */
function outputJsonError(int $code = 500, string $message = '', int $statusCode = 200): JsonResponse
{
    if ($message == '') {
        $message = '参数错误';
    }

    return response()->json(['code' => $code, 'msg' => $message], $statusCode);
}


/**
 * 输出JSON结果
 *
 * @param array $content
 * @param string $message
 * @param int $code
 * @param array $header
 *
 * @return JsonResponse
 */
function outputJsonResult(array $content = [], string $message = '成功', int $code = 200, array $header = []): JsonResponse
{


    $result = [
        'code' => $code,
        'msg' => $message,
        'data' => $content ?: new ArrayObject(),
    ];

    return response()
        ->json($result)
        ->withHeaders($header);
}


/**
 *  手机号验证
 *
 * @param $cellphone string
 *
 * @return bool
 */
function checkValidMobile(string $cellphone): bool
{
    /**
     * 移动号码段: 134、135、136、137、138、139、147、150、151、152、157、158、159、182、183、187、188
     * 联通号码段: 130、131、132、155、156、185、186
     * 电信号码段: 133、153、180、189、181
     */
    if (preg_match("/^(1[3-9][0-9])\d{8}$/", $cellphone)) {
        return true;
    }

    return false;
}


/**
 * 隐藏手机号中间4位
 *
 * @param string $cellphone
 *
 * @return string
 */
function secretCellphone(string $cellphone): string
{
    if (strlen($cellphone) > 8) {
        return substr_replace($cellphone, '****', 3, 4);
    } else {
        return $cellphone;
    }
}


/**
 * 按照预订格式显示时间
 *
 * @param string $format 格式
 * @param int $timestamp 时间
 * @param int $yesterday 时间显示模式：0：标准的年月日模式，1：今天/昨天模式，2：1分钟，1小时，1天等更具体的模式
 *
 * @return string 格式化后的时间串
 */
function formatDate(string $format = 'Ymd', int $timestamp = 0, int $yesterday = 0): string
{
    $timeNow = time();
    $timestamp = $timestamp ?: $timeNow;

    if ($yesterday == 0) {
        $returnDate = date($format, $timestamp);
    } elseif ($yesterday == 1) {
        if (date('Y-m-d', $timestamp) == date('Y-m-d', $timeNow)) {
            $returnDate = __('Today');
        } elseif (date('Y-m-d', $timestamp) == date('Y-m-d', $timeNow - 86400)) {
            $returnDate = __('Yesterday');
        } else {
            $returnDate = date($format, $timestamp);
        }
    } else {
        $timeDiff = $timeNow - $timestamp;

        if ($timeDiff < 0) {
            $returnDate = date($format, $timestamp);
        } elseif ($timeDiff < 60) {
            $returnDate = __('1 minute before');
        } elseif ($timeDiff < 3600) {
            $returnDate = sprintf(__('%d minutes before'), intval($timeDiff / 60));
        } elseif ($timeDiff < 7200) {
            $returnDate = __('1 hour before');
        } elseif ($timeDiff < 86400) {
            $returnDate = sprintf(__('%d hours before'), intval($timeDiff / 3600));
        } elseif ($timeDiff < 172800) {
            $returnDate = __('1 day before');
        } elseif ($timeDiff < 604800) {
            $returnDate = sprintf(__('%d days before'), intval($timeDiff / 86400));
        } elseif ($timeDiff < 1209600) {
            $returnDate = __('1 week before');
        } elseif ($timeDiff < 3024000) {
            $returnDate = sprintf(__('%d weeks before'), intval($timeDiff / 604900));
        } elseif ($timeDiff < 15552000) {
            $returnDate = sprintf(__('%d months before'), intval($timeDiff / 2592000));
        } else {
            $returnDate = date($format, $timestamp);
        }
    }

    return $returnDate;
}


/**
 * 格式化时间，长类型：Y-m-d H:i:s
 *
 * @param int $timestamp 时间
 *
 * @return string
 */
function formatLongDate(int $timestamp = 0): string
{
    return formatDate('Y-m-d H:i:s', $timestamp);
}

/**
 * 获取当前日期
 *
 * @return string
 */
function getNowDate(): string
{
    return checkCli() ? formatLongDate() : date('Y-m-d H:i:s');
}

/**
 * 获取当前时间
 *
 * @return false|string
 */
function getNowTime()
{
    return checkCli() ? time() : TIME_NOW;
}

/**
 * 获取数字默认字符串 0~9
 *
 * @return string
 */
function getNumberDefaultStr(): string
{
    return '0123456789';
}

/**
 * 获取字母(小写)默认字符串
 *
 * @return string
 */
function getLetterLowerDefaultStr(): string
{
    return 'abcdefghijklmnopqrstuvwxyz';
}

/**
 * 获取字母(大写)默认字符串
 *
 * @return string
 */
function getLetterUpperDefaultStr(): string
{
    return 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
}

/**
 * 获取一个指定字符串库
 *
 * @return string
 */
function getBaseStr(): string
{
    return getNumberDefaultStr() . getLetterLowerDefaultStr() . getLetterUpperDefaultStr() . '!#$%&()*+,-.\/:;<=>?@[\\\\\]^_`{|}~';
}

/**
 * 获取伪：唯一码
 * 不可用作全局唯一的场景
 *
 * @param bool $ymd
 * @return string
 */
function getForgedUniCode(bool $ymd = false): string
{
    $code = sha1(uniqid('', true) . str_shuffle(str_repeat(
            getBaseStr(),
            16
        )));
    $ymd && $code = formatDate('YmdHis') . $code;

    return $code;
}

/**
 * 获取一个随机字符串
 *
 * @param int $len 长度
 * @return false|string
 */
function getRandStr(int $len)
{
    $str = str_shuffle(str_repeat(
        uniqid('', true) . getBaseStr(),
        16
    ));

    return substr($str, 0, min($len, strlen($str)));
}


/**
 * 获取类的基本名称,去掉后缀(controller|service|dao）
 *
 * @param string $classPath
 * @param string $emptySuffix
 *
 * @return string|string[]
 */
function getClassBaseName(string $classPath, string $emptySuffix)
{
    $classInfo = explode('\\', $classPath);
    return str_replace($emptySuffix, '', array_pop($classInfo));
}

if (!function_exists('getExceptionMsg')) {
    /**
     * 获取异常内容
     */
    function getExceptionMsg($exception): string
    {
        return "file:" . $exception->getFile() . "|line:" . $exception->getLine() . "|msg:" . $exception->getMessage();
    }
}

/**
 * 蛇形转驼峰
 */
if (!function_exists('snakeToHump')) {
    function snakeToHump($params): array
    {
        $resultData = [];
        foreach ($params as $index => $item) {
            if (is_array($item)) {
                $item = snakeToHump($item);
            }

            $index = ucwords(str_replace(['-', '_'], ' ', $index));
            $index = lcfirst(str_replace(' ', '', $index));
            $resultData[$index] = $item;
        }

        return $resultData;
    }
}

/**
 * 获取验证码
 *
 * @return int
 */
function getValidCode(): int
{
    return mt_rand(100000, 999999);
}


if (!function_exists('getBirthdayYearMonthNum')) {
    /**
     * 根据生日的获取年岁月
     */
    function getBirthdayYearMonthNum($birthday): array
    {
        $resultData = [
            'yearNum' => 0,
            'monthNum' => 0,
        ];

        if ($birthday == "0000-00-00 00:00:00") {
            return $resultData;
        }

        $birthdayTime = strtotime($birthday);

        $birthdayYear = date("Y", $birthdayTime);
        $nowYear = date("Y");

        $birthdayMonth = date("m", $birthdayTime);
        $nowMonth = date("m");

        $yearNum = $nowYear - $birthdayYear;
        $monthNum = $nowMonth - $birthdayMonth;

        if ($monthNum < 0) {
            $yearNum = intval($yearNum) - 1;
            $monthNum = intval($monthNum) + 12;
        }

        $resultData['yearNum'] = $yearNum;
        $resultData['monthNum'] = $monthNum;

        return $resultData;
    }
}

/**
 * 字符串转化为数组，可以按，中英文逗号，换行分割
 *
 * @param $str
 *
 * @return array
 */
function explodeCommaAndLineFeed($str): array
{
    return explode(',', trim(str_replace(["，\r\n", ",\r\n", '，', "\r\n", PHP_EOL], ',', $str), ','));
}

/**
 * 匹配字符串的中文
 *
 * @param string $str 要匹配的字符串
 * @return mixed
 */
function pregStrChinese(string $str)
{
    preg_match_all("/[\x{4e00}-\x{9fa5}]+/u", $str, $matches);

    return $matches;
}

/**
 * 获取指定日期的，自然日 开始、结束日期格式
 *
 * @param string $date
 * @param string $type
 * @return string|string[]
 * @tips type=''        return ['Y-m-d 00:00:00', 'Y-m-d 23:59:59']
 * @tips type='start'    return 'Y-m-d 00:00:00'
 * @tips type='end'    return 'Y-m-d 23:59:59'
 */
function getDayStartEndDate(string $date = '', string $type = '')
{
    if (!$date) {
        $date = formatLongDate();
    }
    $ymd = formatDate('Y-m-d', strtotime($date));
    switch ($type) {
        case 'start':
            return $ymd . ' 00:00:00';
        case 'end':
            return $ymd . ' 23:59:59';
        default:
            return [
                $ymd . ' 00:00:00',
                $ymd . ' 23:59:59',
            ];
    }
}

/**
 * 拼接url参数
 *
 * @param $domain
 * @param $params
 * @return string
 */
function buildUrlParams($domain, $params): string
{
    $url = $domain;
    $query = http_build_query($params);
    if ($query) {
        $url .= '?' . $query;
    }
    return $url;
}

/**
 * 时间戳转RFC3339标准时间格式
 *
 * @return void
 */
function timestampToRFC(int $timestamp): string
{
    // 创建DateTime对象，并设置时间戳
    $datetime = new DateTime();
    $datetime->setTimestamp($timestamp);

    // 设置时区为UTC
    $datetime->setTimezone(new DateTimeZone('Asia/Shanghai'));

    // 格式化为RFC 3339标准格式
    return $datetime->format(DateTimeInterface::RFC3339);
}

if (!function_exists('makeH5Url')) {
    function makeH5Url(string $url): string
    {
        if (!$url) {
            return $url;
        }

        // 兼容字符串第一个元素带 '/' 的场景
        if (substr($url, 0, 1) != DIRECTORY_SEPARATOR) {
            $url = DIRECTORY_SEPARATOR . $url;
        }

        if (env('APP_ENV') == 'production') {
            return env('APP_URL', 'localhost') . '/yjc3h5' . $url;
        } else {
            // @tips 临时方案： 不能直接改env 因为有的地方还需要https， 测试环境的h5暂时没有https
            $appUrl = env('APP_URL', 'localhost');
            $parse_url = parse_url($appUrl);
            $host = $parse_url['host'] ?? $appUrl;

            return 'http://' . $host . '/yjc3h5' . $url;
        }

    }
}


if (!function_exists('ip')) {
    /**
     * Get Client IP.
     *
     * @param array $server
     * @return string
     */
    function ip(array $server): string
    {
        $ip = '';
        if (Arr::get($server, 'HTTP_CLIENT_IP') && strcasecmp(Arr::get($server, 'HTTP_CLIENT_IP'), 'unknown')) {
            $ip = Arr::get($server, 'HTTP_CLIENT_IP');
        } elseif (Arr::get($server, 'HTTP_X_FORWARDED_FOR') && strcasecmp(Arr::get($server, 'HTTP_X_FORWARDED_FOR'), 'unknown')) {
            $ip = Arr::get($server, 'HTTP_X_FORWARDED_FOR');
        } elseif (Arr::get($server, 'REMOTE_ADDR') && strcasecmp(Arr::get($server, 'REMOTE_ADDR'), 'unknown')) {
            $ip = Arr::get($server, 'REMOTE_ADDR');
        } elseif (Arr::has($server, 'REMOTE_ADDR') && strcasecmp(Arr::get($server, 'REMOTE_ADDR'), 'unknown')) {
            $ip = Arr::get($server, 'REMOTE_ADDR');
        }
        //针对负载均衡的情况下会获取代理ip，这里只取第一个用户ip一个，用户端ip
        $ip_array = explode(',', $ip);
        $ip = $ip_array[0];
        return $ip;
    }
}
